<?php

/**
 * Created by PhpStorm.
 * @description:数据库连接池联系
 * @time: 2018年5月15日20:40:15
 * @Author: yfl
 * @QQ 554665488
 * Date: 2018-5-15
 * Time: 20:24
 */
class poolPractise
{
    protected $server;
    protected $db_config; //配置信息

    public function __construct($config)
    {

        //全局对象
        $this->server = new \swoole\server('0.0.0.0', 9501);
        $this->server->set($config['tcp']);
        //注册事件
        $this->server->on('WorkerStart', [$this, 'onWorkerStart']);
        $this->server->on('receive', [$this, 'onReceive']);
        $this->server->on('task', [$this, 'onTask']);
        $this->server->on('finish',[$this,'onFinish']);
        $this->db_config = $config;
        $this->server->start(); //全局生命周期
    }

    /**
     * @description:
     * @time:
     * @Author: yfl
     * @QQ 554665488
     * @param $server
     * @param $worker_id: 连接池id
     */
    public function onWorkerStart($server, $worker_id)
    {
//        var_dump($worker_id);
    }

    /**
     * @description:接收数据的方法
     * @time: 2018年5月15日22:19:54
     * @Author: yfl
     * @QQ 554665488
     * @param $server :swoole 服务对象
     * @param $fd : todo 待了解
     * @param $reactor_id :反应堆id
     * @param $data :接受到的数据
     */
    public function onReceive($server, $fd, $reactor_id, $data)
    {
        $len = unpack('N', $data)[1];
        $body = substr($data, -$len);//去除二进制数据之后 不要包头的数据
        //Sql发送过来的时候发送给连接池
        $result = $server->taskwait($body);
        var_dump($result);
    }

    /*
     * 自带排队效果
     * 没办法控制连接池数量，资源非常昂贵。
     * 多一次进程通讯
     * 长连接服用链接
     * */
    public function onTask($server, $task_id, $worker_id, $data)
    {
//        var_dump($data);
        $res = $this->query($data);
        var_dump($res);
//        $server->finish(json_encode($res));

    }

    public function onFinish($server, $task_id, $data)
    {

    }

    //执行sql
    protected  function query($sql){

        //执行sql的时候,两次循环,如果执行成功,就跳出循环失败
        $db=$this->db_connect($this->db_config);
        for ($i=0;$i<2;$i++){
            try{
                $res=$db->query($sql);
                break;
            }catch (PDOException $e){
                $err_msg=$e->getMessage();
                if(strpos($err_msg,'MySQL server has gone away')!==false){
                    $db=$this->db_connect($this->db_config);
                }
                $res=$db->query($sql);
                break;
            }
        }
        //如果当前是select
        if(preg_match('/^select/i',$sql)){
            $data=$res->fetchAll(PDO::FETCH_ASSOC); //执行查询
        }else{
            $data=$res;
        }
        return $data;
    }

    public  function  db_connect($db_config){
        try{
            $pdo=new PDO($db_config['db']['dsn'],$db_config['db']['user'],$db_config['db']['password'],[PDO::ATTR_PERSISTENT=>true,PDO::ATTR_SERVER_INFO=>true]);
            return $pdo;
        }catch (Exception $e){
            echo $e->getMessage();
            return [];
        }
    }
}

$config['tcp'] = [
    'worker_num' => 2,
    'task_worker_num' => 20,//连接池链接数量
    'open_length_check' => true,
    'package_length_type' => 'N',
    'package_length_offset' => 0, //计算总长度
    'package_body_offset' => 4,//包体位置
];
$config['db'] = [
    'dsn'=>'mysql:host=localhost;dbname=swoole_test',
    'user'=>'root',
    'password' => 'Abc123!Abc'
];
new poolPractise($config);